home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
propdit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
6KB
|
327 lines
/*
* Copyright 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* propdit -
* general propagation dither support.
*
* Paul Haeberli - 1993
*/
#include "stdio.h"
#include "propdit.h"
#define NOISEMAG2 64
#define NOISEPATS 1000
/*
* noise adding stuff follows . . .
*
*/
static initnoise(pd)
propdit *pd;
{
int n;
int *nptr;
n = NOISEPATS+pd->xsize;
pd->noise = (int *)malloc(n*sizeof(int));
nptr = pd->noise;
srandom(getpid());
while(n--)
*nptr++ = 128+(random()%(NOISEMAG2+1))-(NOISEMAG2/2);
}
/*
* Cheap 2 weight dither
*
*/
static int bmditherrow2(pd,buf,bits)
propdit *pd;
short *buf;
unsigned char *bits;
{
int i, maskbit;
int error, rerror, rwant;
int *nptr;
int *error0, *error1;
int n;
n = pd->xsize;
if(!pd->noise)
initnoise(pd);
nptr = pd->noise+(random()%NOISEPATS);
if(pd->cury&1) {
error0 = pd->err0+1;
error1 = pd->err1+1;
maskbit = 0x80;
for(i=0; i<n; i++ ) {
rerror = (error1[i-1]+error0[i])>>1;
if(*buf == 0 || *buf == 255) {
rwant = *buf + rerror;
if(*buf++ == 255) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
} else {
rwant = *buf++ + rerror;
if(rwant>*nptr++) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
}
error1[i] = error;
maskbit >>= 1;
if(!maskbit) {
maskbit = 0x80;
bits++;
}
}
} else {
error0 = pd->err1+1;
error1 = pd->err0+1;
buf+=(n-1);
bits = bits + ((n-1)/8);
maskbit = 0x80>>((n-1)%8);
for(i=n; i--;) {
rerror = (error1[i+1]+error0[i])>>1;
if(*buf == 0 || *buf == 255) {
rwant = *buf + rerror;
if(*buf-- == 255) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
} else {
rwant = *buf-- + rerror;
if(rwant>*nptr++) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
}
error1[i] = error;
maskbit <<= 1;
if(maskbit&0x100) {
maskbit = 0x01;
bits--;
}
}
}
}
#define ERRMAG3 64
/*
* Use 3 spots to contribute error . . .
*
*/
static int bmditherrow3(pd,buf,bits)
propdit *pd;
short *buf;
unsigned char *bits;
{
int n, i, maskbit;
int error, rerror, rnext, rwant;
int *error0;
n = pd->xsize;
maskbit = 0x80;
rerror = (random()%ERRMAG3)-(ERRMAG3/2);
error0 = pd->err0+1;
rnext = error0[0] = 0;
for(i=0; i<n; i++ ) {
rwant = *buf++ + rerror + rnext;
if(rwant>128) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
rerror = (3*error)/8;
error0[i] += rerror;
rnext = error0[i+1];
error0[i+1] = error-2*rerror;
maskbit = maskbit>>1;
if(!maskbit) {
maskbit = 0x80;
bits++;
}
}
}
/*
* Thad suggested this technique. Uses 4 spots to contribute error.
*
*/
static int bmditherrow4(pd,buf,bits)
propdit *pd;
short *buf;
unsigned char *bits;
{
int n, i, maskbit;
int error, rerror, rwant;
int *error0, *error1;
n = pd->xsize;
if(pd->cury&1) {
error0 = pd->err0+1;
error1 = pd->err1+1;
} else {
error0 = pd->err1+1;
error1 = pd->err0+1;
}
maskbit = 0x80;
for(i=0; i<n; i++ ) {
rerror = (error1[i-1]+error0[i-1]+error0[i]+error0[i+1]+2)>>2;
rwant = *buf++ + rerror;
if(rwant>128) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
error1[i] = error;
maskbit = maskbit>>1;
if(!maskbit) {
maskbit = 0x80;
bits++;
}
}
}
/*
* True Floyd and Steinberg dither
*
*/
static int bmditherrowfloyd(pd,buf,bits)
propdit *pd;
short *buf;
unsigned char *bits;
{
int n, i, maskbit;
int error, rerror, rwant;
int *error0, *error1;
n = pd->xsize;
maskbit = 0x80;
if(pd->cury&1) {
error0 = pd->err0+1;
error1 = pd->err1+1;
for(i=0; i<n; i++ ) {
rerror = (7*error1[i-1]+error0[i-1]+5*error0[i]+3*error0[i+1]+2)>>4;
rwant = *buf++ + rerror;
if(rwant>128) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
error1[i] = error;
maskbit >>= 1;
if(!maskbit) {
maskbit = 0x80;
bits++;
}
}
} else {
error0 = pd->err1+1;
error1 = pd->err0+1;
buf+=(n-1);
maskbit = 0x80>>((n-1)%8);
bits = bits + ((n-1)/8);
for(i=n; i--;) {
rerror = (7*error1[i+1]+error0[i+1]+5*error0[i]+3*error0[i-1]+2)>>4;
rwant = *buf-- + rerror;
if(rwant>128) {
error = rwant-255;
} else {
error = rwant-0;
*bits |= maskbit;
}
error1[i] = error;
maskbit <<= 1;
if(maskbit&0x100) {
maskbit = 0x01;
bits--;
}
}
}
}
propdit *newpropdit(xsize,dittype)
int xsize, dittype;
{
propdit *pd;
pd = (propdit *)malloc(sizeof(propdit));
switch(dittype) {
case PROPDIT2:
pd->ditfunc = bmditherrow2;
break;
case PROPDIT3:
pd->ditfunc = bmditherrow3;
break;
case PROPDIT4:
pd->ditfunc = bmditherrow4;
break;
case PROPDITFS:
pd->ditfunc = bmditherrowfloyd;
break;
default:
fprintf(stderr,"newpropdit: bad dittype %d\n",dittype);
exit(1);
}
pd->xsize = xsize;
pd->cury = 0;
pd->err0 = (int *)malloc((xsize+2)*sizeof(int));
pd->err1 = (int *)malloc((xsize+2)*sizeof(int));
bzero(pd->err0,(xsize+2)*sizeof(int));
bzero(pd->err1,(xsize+2)*sizeof(int));
pd->noise = 0;
return pd;
}
freepropdit(pd)
propdit *pd;
{
if(pd->err0)
free(pd->err0);
if(pd->err1)
free(pd->err1);
if(pd->noise)
free(pd->noise);
free(pd);
}
propditrow(pd,sbuf,bbuf)
propdit *pd;
short *sbuf;
unsigned char *bbuf;
{
int outbytes;
outbytes = 1+((pd->xsize-1)>>3);
bzero(bbuf,outbytes);
pd->ditfunc(pd,sbuf,bbuf);
pd->cury++;
}